/**
主要回顾：内部类

内部类：
    1.成员内部类
        1.1 访问格式：
            1.1.1 在外部类中创建方法访问内部类，其他类通过外部类对象的方法访问内部类
            1.1.2 直接在其他类中创建内部类对象，通过该对象访问内部类
            
        1.2 内部类的好处：内部类可以访问外部类的所有成员
        
        1.3 内部类的应用场景：当描述事物 A 的时候，若 A 的内部还有另外一个事物 B，而该 B 需要访问 A 的属性，则可以使用内部类
        
    2.局部内部类：方法内部的类
        1.1 访问格式：在方法里创建对象来访问
        
    3.匿名内部类：匿名指没有名
        需要存在继承或实现关系才能使用，一般用于实参
*/

//抽象类
abstract class Animal{
    public abstract Animal run();    //本应该为 void，为了返回 this，声明为 Animal
    public abstract void sleep();
}

//接口
interface Dao{
    public void add();
    public void delete();
}

//外部类
class Outer{
    int x = 1;
    //成员内部类
    class Inner{
        int x = 2;
        public void print(){
            System.out.println("print in Inner... " + x);    //访问内部的 x
            System.out.println("print in Inner... " + Outer.this.x);    //访问外部的 x
        }
    }
    //成员内部类的调用方法
    public void instance(){
        Inner inner = new Inner();
        inner.print();
    }
    
    //静态成员内部类
    static class StaticInner{
        static int i = 3;    //如果定义了静态变量，则该内部类也必须是静态的
        public void print(){
             System.out.println("print in Static Inner... " + i);
        }
    }
    
    //局部内部类
    public void test(){
        class LocalInner{
            public void localPrint(){
                System.out.println("print in Local Inner");
            }
        }
    }
    
    //匿名内部类——抽象类作实参
    public void AnonymousF(){
        new Animal(){
            public Animal run(){
                System.out.println("running...");
                return this;    //返回一个 Animal 对象，以调用 sleep 方法
            }
            
            public void sleep(){
                System.out.println("sleeping...");
            }
        }.run().sleep();
    }

    //匿名内部类——接口作实参
    public void AnonymousI(){
        new Dao(){
            public void add(){
                System.out.println("add...");
            }
            
            public void delete(){}
        }.add();
    }    
    
}

class LearnInnerClass {
    public static void main(String[] args) {
        
        //访问方式一：通过外部类对象
        Outer outer = new Outer();
        outer.instance();
        
        
        //访问方式二：直接创建内部类对象
        Outer.Inner inner = new Outer().new Inner();
        inner.print();
        
        //静态内部类的另外一种访问方式
        System.out.println(Outer.StaticInner.i);           //不需要对象，直接通过类名访问
        Outer.StaticInner si = new Outer.StaticInner();    //不需要对象，直接通过类名找到
        si.print();
        
        outer.AnonymousF();
        outer.AnonymousI();
    }
}